package com.lagou.rpc.server.handler;

import com.lagou.rpc.common.converter.Converter;
import com.lagou.rpc.common.entity.RPCMethodMetaData;
import com.lagou.rpc.common.entity.RPCRequestData;
import com.lagou.rpc.common.entity.SimpleRpcResponseBuilder;
import com.lagou.rpc.common.handler.RequestHandler;
import com.lagou.rpc.server.SimpleRpcMethod;
import com.lagou.rpc.server.SimpleRpcMethodRegistry;

import java.lang.reflect.Method;

/**
 * RPCRequestDataRequestHandler
 *
 * @author wlz
 * @date 2020/4/30
 */
public class RPCRequestDataRequestHandler implements RequestHandler<RPCRequestData> {
    private SimpleRpcMethodRegistry simpleRpcMethodRegistry;
    private Converter converter;

    public RPCRequestDataRequestHandler(SimpleRpcMethodRegistry simpleRpcMethodRegistry,
                                        Converter converter) {
        this.simpleRpcMethodRegistry = simpleRpcMethodRegistry;
        this.converter = converter;
    }

    @Override
    public Object handle(RPCRequestData data) {
        // 获取方法id
        String methodId = data.getMethodId();
        // 从方法注册中心中获取方法调用信息
        SimpleRpcMethod rpcMethod = simpleRpcMethodRegistry.getRpcMethod(methodId);
        RPCMethodMetaData methodMetaData = rpcMethod.getMethodMetaData();
        // 构建参数
        Object[] params = buildParams(data.getParams(), methodMetaData.getParamTypes());
        // 方法执行
        Method method = rpcMethod.getMethod();
        Object serviceInstance = rpcMethod.getServiceInstance();
        try {
            Object result = method.invoke(serviceInstance, params);
            return SimpleRpcResponseBuilder.buildSuccessResponse(converter.obj2Bytes(result));
        } catch (Throwable e) {
            return SimpleRpcResponseBuilder.buildErrorResponse(e);
        }
    }

    private Object[] buildParams(byte[][] paramBytes, Class[] paramTypes) {
        Object[] params;
        if (paramBytes != null && paramBytes.length != 0) {
            params = new Object[paramBytes.length];
        } else {
            return null;
        }
        for (int i = 0; i < paramBytes.length; i++) {
            params[i] = converter.bytes2Obj(paramBytes[i], paramTypes[i]);
        }
        return params;
    }


}
